package org.anderground.modules.editor.importers.pmz.map;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import org.anderground.core.Logger;
import org.anderground.core.model.Line;
import org.anderground.core.model.ModelData.Builder;
import org.anderground.core.util.Coord;

public class PmzLine {
	private Line line;
	HashMap<String, StationEntry> entryMap = new HashMap<String, StationEntry>();
	
	private List<StationEntry> stations = new ArrayList<StationEntry>();
	
	/**
	 * 
	 * @param lineName name of line
	 * @param color - color of line
	 */
	public PmzLine(String lineName, java.awt.Color color, int delay) {
		this.line=new Line(lineName, color.getRGB(),delay);
	}
	
	public void setLine(Line line) {
		this.line = line;
	}
	public void addStation(String name, String[] previuosStations, String[] nextStations, Coord coord) {
		StationEntry s = new StationEntry(name,previuosStations,nextStations,coord);
		s.complex = true;
		stations.add(s);
		
	}
	
	public void addStation(String name, String previuosStation, Coord coord) {
		if(previuosStation!=null) {
			stations.add(new StationEntry(name,new String[]{previuosStation},null,coord));
			entryMap.get(previuosStation).addNext(name);
		}
		else
			stations.add(new StationEntry(name,null,null,coord));
		
	}
	
	/**
	 * call only after parsing times
	 */
	public void linkStations() {
		for(StationEntry se:stations) {
			clearFromEmpty(se.previuosStations);
			clearFromEmpty(se.nextStations);
			for(String prev: se.getPreviuosStations()) {
				if(entryMap.get(prev)==null) System.out.println(prev + " not registred"); else
					entryMap.get(prev).addNext(se.getName());
			}
		}
	}
	
	private void clearFromEmpty(List<String> list) {
		for(int i=0;i<list.size();i++) {
			if(list.get(i).equals(""))
				list.remove(i);
		}
	}
	public Line getLine() {
		return line;
	}
	public class TransitionEntry {
		int time;
		String from, to;
		public TransitionEntry(String from, String to, int time) {
			this.from = from;
			this.to=to;
			this.time = time;
		}
	}
	public class StationEntry {
		private String codeName,alias=null;
		boolean complex = false;
		List<String> previuosStations = new ArrayList<String>();
		List<String> nextStations = new ArrayList<String>();
		List<TransitionEntry> tunnels = new ArrayList<TransitionEntry>();
		List<TransitionEntry> transfers = new ArrayList<TransitionEntry>();
		
		private Coord coord; 
		StationEntry linkTo;
		public StationEntry(String name, String[] previuosStations, String[] nextStations, Coord coord) {
			this.codeName = name;
			if(previuosStations!=null)
				this.previuosStations.addAll(Arrays.asList(previuosStations));
			if(nextStations!=null)
				this.nextStations.addAll(Arrays.asList(nextStations));
			this.coord = coord;
			entryMap.put(name, this);
		}
		
		public boolean isComplex() {
			return complex;
		}
		public void setTimeToSingleNext(int time) {
			if(nextStations.size()==0) return;
			StationEntry entry = entryMap.get(nextStations.get(0));
			entry.tunnels.add(new TransitionEntry(entry.getName(),this.getName(),time));
			this.tunnels.add(new TransitionEntry(this.getName(),entry.getName(),time));
		}
		public void addOutTunnelTime(String to, int time) {
			
			if(entryMap.get(to)!=null)
			this.addTunnel(to,time);
		}
		
		public void addInTunnelTime(String from, int time) {
			StationEntry entry = entryMap.get(from);
			
			if(entry!=null)
			entry.addTunnel(this.getName(),time);
			
		}
		public void addTunnel(String to, int time) {
			for(TransitionEntry te:tunnels) {
				if(te.to.equals(to)) return;
			}
			this.tunnels.add(new TransitionEntry(this.getName(),to,time));
		}
		public void addNext(String next) {
			if(!this.nextStations.contains(next)) {
				this.nextStations.add(next);
			}
			
		}
		
		public void addPrev(String prev) {
			if(!this.previuosStations.contains(prev)) {
				this.previuosStations.add(prev);
			}
			
		}
		public String getName() {
			return codeName;
		}
		public String getPresentName() {
			return (alias==null)?codeName:alias;
		}
		public void setAlias(String name) {
			this.alias= name;
		}
		
		public String[] getPreviuosStations() {
			return previuosStations.toArray(new String[0]);
		}
		
		public String[] getNextStations() {
			return nextStations.toArray(new String[0]);
		}
		
		public int getX() {
			return coord.getX();
		}
		
		public int getY() {
			return coord.getY();
		}
		
		public String toString() {
			String str = codeName + ":\n";
			for(String s:previuosStations) {
				str+=s + "->" + codeName + "\n"; 
			}
			for(String s:nextStations) {
				str+=s + "<-" + codeName + "\n"; 
			}
			return str;
		}

		public void addTransfer(String to, int time) {
			transfers.add(new TransitionEntry(line.getName() + this.getName(),to,time));
		}

		public void linkTo(StationEntry to) {
			if(to.linkTo==null)
				this.linkTo = to;
			else this.linkTo = to.linkTo;
			
		}
		public Line getLine() {
			return line;
		}
	}

	public StationEntry[] getStations() {
		
		return stations.toArray(new StationEntry[0]);
	}

	public void build(Builder builder) {
		
		
	}

	public void setStationNamesToAliases(String[] values) {
		if(values==null) return;
		for(int i=0;i<values.length;i+=2) {
			entryMap.get(values[i]).setAlias(values[i+1]);
			Logger.i("old name:" + values[i] +"\n new name:" + values[i+1]);
		}
		
	}

	public String getName() {
		return line.getName();
	}

	public void removeZeroSizeTunnels() {
		for(PmzLine.StationEntry entry: stations) {
			List<PmzLine.TransitionEntry> tunnelsToRemove = new ArrayList<TransitionEntry>();
			for(PmzLine.TransitionEntry te:entry.tunnels) {
				if(te.time==0) tunnelsToRemove.add(te);
			}
			entry.tunnels.removeAll(tunnelsToRemove);
		}
		
	}

	public void completeTunnels() {
		for(PmzLine.StationEntry entry: stations) {
			for(PmzLine.TransitionEntry te:entry.tunnels) {
				boolean backTunnelExist = false;
				for(TransitionEntry te2: entryMap.get(te.to).tunnels) {
					if(te2.to.equals(entry.codeName)) backTunnelExist=true;
				}
				if(!backTunnelExist) {
					entryMap.get(te.to).addOutTunnelTime(entry.codeName, te.time);
				}
			}
		}
		
	}

	public void removeIsolatedStations() {
		List<PmzLine.StationEntry> toRemove = new ArrayList<StationEntry>();
		for(PmzLine.StationEntry entry: stations) {
			if(entry.tunnels.isEmpty()) toRemove.add(entry);
		}
		stations.removeAll(toRemove);
		
	}
	
	
	
	

}
